<template>
  <div class="form-designer-mid">
    <div class="menu">
      <div class="menu-left">
        <el-tag v-for="tag in tags" :key="tag.name" effect="plain" :closable="tag.name !== '总览'"
          :class="[tag.selected ? 'tag-selected' : '']" @click="selectTag(tag)" @close="removeTag(tag)">
          <div v-if="tag.name === '总览'" style="display: flex; align-items: center;gap: 2px;">
            <div class="edit-icon">
              <SvgGridLine viewBox="0 0 24 24" />
            </div>
            <div>总览</div>
          </div>
          <div v-else>{{ tag.name }}</div>
        </el-tag>
      </div>
      <div class="menu-right">
        <div class="zoom-controls">
          <el-button size="small" @click="zoomOut" :disabled="canvasScale <= minScale">-</el-button>
          <el-input-number v-model="zoomInputValue" :min="minScale * 100" :max="maxScale * 100" :step="1" size="small"
            controls-position="right" @change="handleZoomInputChange" class="zoom-input" />
          <span class="zoom-percent">%</span>
          <el-button size="small" @click="zoomIn" :disabled="canvasScale >= maxScale">+</el-button>
          <el-button size="small" @click="resetZoom">重置</el-button>
          <el-dropdown @command="handleZoomCommand" trigger="click">
            <el-button size="small">
              预设 <el-icon>
                <ArrowDown />
              </el-icon>
            </el-button>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item command="25">25%</el-dropdown-item>
                <el-dropdown-item command="50">50%</el-dropdown-item>
                <el-dropdown-item command="75">75%</el-dropdown-item>
                <el-dropdown-item command="100">100%</el-dropdown-item>
                <el-dropdown-item command="125">125%</el-dropdown-item>
                <el-dropdown-item command="150">150%</el-dropdown-item>
                <el-dropdown-item command="200">200%</el-dropdown-item>
                <el-dropdown-item command="300">300%</el-dropdown-item>
                <el-dropdown-item command="400">400%</el-dropdown-item>
                <el-dropdown-item command="500">500%</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </div>
      </div>
    </div>
    <!-- <div class="canvas-container" ref="canvasContainer" @wheel="handleWheel" @touchstart="handleTouchStart"
      @touchmove="handleTouchMove" @touchend="handleTouchEnd" @gesturestart="handleGestureStart"
      @gesturechange="handleGestureChange" @gestureend="handleGestureEnd"> -->
    <div class="canvas-container" ref="canvasContainer">
      <!-- 布局模式 -->
      <div class="form-canvas" :style="canvasStyle" @dragover="handleDragOver" @dragenter="handleDragEnter"
        @dragleave="handleDragLeave" @drop="handleDrop" :class="{ 'drag-over': isDragOver, 'dragging': isDragging }"
        @mousedown="handleMouseDown" @mousemove="handleMouseMove" @mouseup="handleMouseUp">

        <!-- 拖动状态指示器 -->
        <div v-if="isDragging" class="drag-indicator">
          <div class="drag-text">拖动中...</div>
        </div>

        <div class="form-fields">
          <div v-for="field in currentForm.fields" :key="field.id || `field-${Math.random()}`"
            :class="['field-item', { selected: selectedField?.id === field.id }]" @click="selectField(field)"
            :style="getFieldStyle(field)">

            <!-- 根据字段类型渲染不同的输入组件 -->
            <div class="field-input">
              <Component :is="getComponentName(field.type)" :value="field.attrs.modelValue || ''" :attrs="field.attrs"
                :disabled="field.attrs.disabled" />
            </div>

            <!-- 字段操作按钮 -->
            <div class="field-actions" v-if="selectedField?.id === field.id">
              <el-button size="small" @click.stop="editField(field)">编辑</el-button>
              <el-button size="small" type="danger" @click.stop="removeField(field.id)">删除</el-button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, onMounted, onUnmounted } from 'vue'
import { useFormDesignerStore, type FormField } from '@/stores/formDesigner'
import SvgGridLine from '@/assets/svg/grid_line.svg'
import { getComponentDefaultAttrs } from '@/components/IFormComponents/componentConfigs'
import { ArrowDown } from '@element-plus/icons-vue'

interface TagsItem {
  name: string
  selected: boolean
}

const tags = ref<TagsItem[]>([
  { name: '总览', selected: true },
  { name: 'Tag 1', selected: false },
  { name: 'Tag 2', selected: false },
  { name: 'Tag 3', selected: false },
  { name: 'Tag 4', selected: false },
  { name: 'Tag 5', selected: false },
])

const selectTag = (tag: TagsItem) => {
  tags.value.forEach(tag => {
    tag.selected = false
  })
  tag.selected = true
}

const removeTag = (tag: TagsItem) => {
  console.log('removeTag', tag)
}
const formDesignerStore = useFormDesignerStore()

// 拖拽状态
const isDragOver = ref(false)

// 画布拖动状态
const isDragging = ref(false)
const dragStart = ref({ x: 0, y: 0 })
const canvasPosition = ref({ x: 0, y: 0 })
const canvasContainer = ref<HTMLElement>()

// 触摸和手势状态
const touchState = ref({
  isTouching: false,
  touches: [] as Touch[],
  lastTouchDistance: 0,
  lastTouchCenter: { x: 0, y: 0 },
  initialScale: 1,
  initialPosition: { x: 0, y: 0 }
})

// 画布缩放状态
const canvasScale = ref(1)
const minScale = 0.1
const maxScale = 5
const scaleStep = 0.05  // 减小步长，提高精准度
const wheelScaleStep = 0.02  // 滚轮缩放使用更小的步长

// 缩放输入框的值
const zoomInputValue = computed({
  get: () => Math.round(canvasScale.value * 100),
  set: (value: number) => {
    if (value >= minScale * 100 && value <= maxScale * 100) {
      canvasScale.value = value / 100
    }
  }
})

// 从store获取数据
const currentForm = computed(() => formDesignerStore.currentForm)
const selectedField = computed(() => formDesignerStore.selectedField)

// 画布样式
const canvasStyle = computed(() => ({
  transform: `translate(${canvasPosition.value.x}px, ${canvasPosition.value.y}px) scale(${canvasScale.value})`,
  cursor: isDragging.value ? 'grabbing' : 'grab',
  transformOrigin: 'center center'
}))

// 获取字段样式
const getFieldStyle = (field: FormField) => {
  return {
    ...field.style,
    position: 'relative' as const
  }
}

// 获取组件名称
const getComponentName = (type: string) => {
  const componentMap: Record<string, string> = {
    'IFormInput': 'IFormInput',
    'IFormLayout': 'IFormLayout',
    'IFormTable': 'IFormTable',
    'input': 'IFormInput',
    'layout': 'IFormLayout',
    'table': 'IFormTable',
    'textarea': 'el-input',
    'select': 'el-select',
    'radio': 'el-radio-group',
    'checkbox': 'el-checkbox',
    'date': 'el-date-picker',
    'number': 'el-input-number'
  }
  return componentMap[type] || 'IFormInput'
}


// 选择字段
const selectField = (field: FormField) => {
  formDesignerStore.selectField(field)
}

// 编辑字段
const editField = (field: FormField) => {
  // 这里可以打开字段编辑对话框
  console.log('编辑字段:', field)
}

// 删除字段
const removeField = (fieldId: string | null) => {
  if (fieldId) {
    formDesignerStore.removeField(fieldId)
  }
}

// 拖拽处理函数
const handleDragOver = (event: DragEvent) => {
  event.preventDefault()
  event.dataTransfer!.dropEffect = 'copy'
}

const handleDragEnter = (event: DragEvent) => {
  event.preventDefault()
  isDragOver.value = true
}

const handleDragLeave = (event: DragEvent) => {
  event.preventDefault()
  // 只有当离开整个画布区域时才设置为false
  if (!(event.currentTarget as Element)?.contains(event.relatedTarget as Node)) {
    isDragOver.value = false
  }
}

const handleDrop = (event: DragEvent) => {
  event.preventDefault()
  isDragOver.value = false

  try {
    const data = JSON.parse(event.dataTransfer!.getData('application/json'))
    console.log(data)
    if (data.type === 'form-field') {
      // 创建新的表单字段
      const newField: Omit<FormField, 'id'> = {
        name: data.componentType,
        nickName: data.componentName,
        type: data.componentType,
        icon: data.icon,
        parentId: 'root',
        slot: null,
        isShow: true,
        attrs: {
          ...getDefaultAttrs(data.componentType),
          label: data.componentName,
          placeholder: `请输入${data.componentName}`,
          required: false
        },
        style: {
          width: 200,
          height: 40,
          x: 0,
          y: 0
        }
      }

      // 添加到表单
      formDesignerStore.addField(newField)

      console.log('成功添加字段:', newField)
    }
  } catch (error) {
    console.error('拖拽数据解析失败:', error)
  }
}

// 获取默认属性
const getDefaultAttrs = (componentType: string): Record<string, unknown> => {
  return getComponentDefaultAttrs(componentType)
}

// 画布拖动事件处理
const handleMouseDown = (event: MouseEvent) => {
  // 只允许在画布空白区域拖动，避免与字段交互冲突
  if (event.target === event.currentTarget || (event.target as HTMLElement).classList.contains('form-fields')) {
    event.preventDefault()
    event.stopPropagation()
    isDragging.value = true
    dragStart.value = {
      x: event.clientX - canvasPosition.value.x,
      y: event.clientY - canvasPosition.value.y
    }

    // 添加全局鼠标事件监听，使用capture模式确保事件优先处理
    document.addEventListener('mousemove', handleGlobalMouseMove, { passive: false, capture: true })
    document.addEventListener('mouseup', handleGlobalMouseUp, { passive: false, capture: true })

    // 阻止文本选择和拖拽
    document.body.style.userSelect = 'none'
    document.body.style.setProperty('-webkit-user-select', 'none')
    document.body.style.setProperty('-moz-user-select', 'none')
    document.body.style.setProperty('-ms-user-select', 'none')
    document.body.style.cursor = 'grabbing'
  }
}

const handleMouseMove = (event: MouseEvent) => {
  if (isDragging.value) {
    event.preventDefault()
    event.stopPropagation()
    updateCanvasPosition(event.clientX, event.clientY)
  }
}

const handleMouseUp = () => {
  if (isDragging.value) {
    isDragging.value = false
    // 移除全局事件监听
    document.removeEventListener('mousemove', handleGlobalMouseMove, { capture: true })
    document.removeEventListener('mouseup', handleGlobalMouseUp, { capture: true })

    // 恢复文本选择和光标
    document.body.style.userSelect = ''
    document.body.style.setProperty('-webkit-user-select', '')
    document.body.style.setProperty('-moz-user-select', '')
    document.body.style.setProperty('-ms-user-select', '')
    document.body.style.cursor = ''
  }
}

const handleGlobalMouseMove = (event: MouseEvent) => {
  if (isDragging.value) {
    event.preventDefault()
    event.stopPropagation()
    updateCanvasPosition(event.clientX, event.clientY)
  }
}

const handleGlobalMouseUp = () => {
  if (isDragging.value) {
    isDragging.value = false
    // 移除全局事件监听
    document.removeEventListener('mousemove', handleGlobalMouseMove, { capture: true })
    document.removeEventListener('mouseup', handleGlobalMouseUp, { capture: true })

    // 恢复文本选择和光标
    document.body.style.userSelect = ''
    document.body.style.setProperty('-webkit-user-select', '')
    document.body.style.setProperty('-moz-user-select', '')
    document.body.style.setProperty('-ms-user-select', '')
    document.body.style.cursor = ''
  }
}

const updateCanvasPosition = (clientX: number, clientY: number) => {
  if (!canvasContainer.value) return

  const containerRect = canvasContainer.value.getBoundingClientRect()
  const newX = clientX - dragStart.value.x
  const newY = clientY - dragStart.value.y

  // 计算边界限制 - 更宽松的边界，允许更多拖动空间
  const canvasWidth = containerRect.width * canvasScale.value
  const canvasHeight = containerRect.height * canvasScale.value

  // 允许画布移动超出容器边界，但保留一定的可见区域
  const minX = -canvasWidth + 200 // 允许画布向左移动，但保留200px可见
  const maxX = containerRect.width - 200  // 允许画布向右移动，但保留200px可见
  const minY = -canvasHeight + 200 // 允许画布向上移动，但保留200px可见
  const maxY = containerRect.height - 200  // 允许画布向下移动，但保留200px可见

  // 应用边界限制
  canvasPosition.value = {
    x: Math.max(minX, Math.min(maxX, newX)),
    y: Math.max(minY, Math.min(maxY, newY))
  }
}

// 缩放相关函数
const handleWheel = (event: WheelEvent) => {
  event.preventDefault()
  event.stopPropagation()

  // 使用更精细的滚轮缩放步长
  const delta = event.deltaY > 0 ? -wheelScaleStep : wheelScaleStep
  const newScale = Math.max(minScale, Math.min(maxScale, canvasScale.value + delta))

  if (newScale !== canvasScale.value) {
    // 计算鼠标位置相对于容器的坐标
    const containerRect = canvasContainer.value?.getBoundingClientRect()
    if (containerRect) {
      // 获取鼠标在容器中的位置
      const mouseX = event.clientX - containerRect.left
      const mouseY = event.clientY - containerRect.top

      // 计算容器中心点
      const containerCenterX = containerRect.width / 2
      const containerCenterY = containerRect.height / 2

      // 计算鼠标相对于容器中心的位置
      const mouseOffsetX = mouseX - containerCenterX
      const mouseOffsetY = mouseY - containerCenterY

      // 计算缩放比例
      const scaleRatio = newScale / canvasScale.value

      // 计算新的画布位置，使鼠标位置保持不变
      const newX = canvasPosition.value.x - mouseOffsetX * (scaleRatio - 1)
      const newY = canvasPosition.value.y - mouseOffsetY * (scaleRatio - 1)

      canvasScale.value = newScale
      canvasPosition.value = { x: newX, y: newY }
    } else {
      canvasScale.value = newScale
    }
  }
}

const zoomIn = () => {
  const newScale = Math.min(maxScale, canvasScale.value + scaleStep)
  if (newScale !== canvasScale.value) {
    // 以画布中心为缩放点
    const containerRect = canvasContainer.value?.getBoundingClientRect()
    if (containerRect) {
      const containerCenterX = containerRect.width / 2
      const containerCenterY = containerRect.height / 2

      const scaleRatio = newScale / canvasScale.value
      const newX = canvasPosition.value.x - (containerCenterX - canvasPosition.value.x) * (scaleRatio - 1)
      const newY = canvasPosition.value.y - (containerCenterY - canvasPosition.value.y) * (scaleRatio - 1)

      canvasScale.value = newScale
      canvasPosition.value = { x: newX, y: newY }
    } else {
      canvasScale.value = newScale
    }
  }
}

const zoomOut = () => {
  const newScale = Math.max(minScale, canvasScale.value - scaleStep)
  if (newScale !== canvasScale.value) {
    // 以画布中心为缩放点
    const containerRect = canvasContainer.value?.getBoundingClientRect()
    if (containerRect) {
      const containerCenterX = containerRect.width / 2
      const containerCenterY = containerRect.height / 2

      const scaleRatio = newScale / canvasScale.value
      const newX = canvasPosition.value.x - (containerCenterX - canvasPosition.value.x) * (scaleRatio - 1)
      const newY = canvasPosition.value.y - (containerCenterY - canvasPosition.value.y) * (scaleRatio - 1)

      canvasScale.value = newScale
      canvasPosition.value = { x: newX, y: newY }
    } else {
      canvasScale.value = newScale
    }
  }
}

const resetZoom = () => {
  canvasScale.value = 1
  canvasPosition.value = { x: 0, y: 0 }
}

// 处理缩放命令
const handleZoomCommand = (command: string) => {
  const targetScale = parseInt(command) / 100
  if (targetScale >= minScale && targetScale <= maxScale) {
    canvasScale.value = targetScale
    // 保持当前位置，只改变缩放比例
  }
}

// 处理缩放输入框变化
const handleZoomInputChange = (value: number | null) => {
  if (value !== null && value >= minScale * 100 && value <= maxScale * 100) {
    canvasScale.value = value / 100
  }
}

// 键盘快捷键处理
const handleKeyDown = (event: KeyboardEvent) => {
  // 检查是否按住了 Ctrl 键
  if (event.ctrlKey || event.metaKey) {
    switch (event.key) {
      case '=':
      case '+':
        event.preventDefault()
        zoomIn()
        break
      case '-':
        event.preventDefault()
        zoomOut()
        break
      case '0':
        event.preventDefault()
        resetZoom()
        break
    }
  }
}

// 触摸事件处理
const handleTouchStart = (event: TouchEvent) => {
  event.preventDefault()
  event.stopPropagation()
  event.stopImmediatePropagation()
  touchState.value.isTouching = true
  touchState.value.touches = Array.from(event.touches)

  if (event.touches.length === 1) {
    // 单指拖动
    const touch = event.touches[0]
    dragStart.value = {
      x: touch.clientX - canvasPosition.value.x,
      y: touch.clientY - canvasPosition.value.y
    }
    isDragging.value = true
  } else if (event.touches.length === 2) {
    // 双指缩放
    const touch1 = event.touches[0]
    const touch2 = event.touches[1]
    const distance = getTouchDistance(touch1, touch2)
    const center = getTouchCenter(touch1, touch2)

    touchState.value.lastTouchDistance = distance
    touchState.value.lastTouchCenter = center
    touchState.value.initialScale = canvasScale.value
    touchState.value.initialPosition = { ...canvasPosition.value }
  }
}

const handleTouchMove = (event: TouchEvent) => {
  event.preventDefault()
  event.stopPropagation()
  event.stopImmediatePropagation()

  if (event.touches.length === 1 && isDragging.value) {
    // 单指拖动
    const touch = event.touches[0]
    updateCanvasPosition(touch.clientX, touch.clientY)
  } else if (event.touches.length === 2) {
    // 双指缩放
    const touch1 = event.touches[0]
    const touch2 = event.touches[1]
    const distance = getTouchDistance(touch1, touch2)
    const center = getTouchCenter(touch1, touch2)

    if (touchState.value.lastTouchDistance > 0) {
      const scaleRatio = distance / touchState.value.lastTouchDistance
      const newScale = Math.max(minScale, Math.min(maxScale, touchState.value.initialScale * scaleRatio))

      // 计算缩放中心点
      const containerRect = canvasContainer.value?.getBoundingClientRect()
      if (containerRect) {
        const centerX = center.x - containerRect.left
        const centerY = center.y - containerRect.top

        const scaleChange = newScale / touchState.value.initialScale
        const newX = touchState.value.initialPosition.x - (centerX - touchState.value.initialPosition.x) * (scaleChange - 1)
        const newY = touchState.value.initialPosition.y - (centerY - touchState.value.initialPosition.y) * (scaleChange - 1)

        canvasScale.value = newScale
        canvasPosition.value = { x: newX, y: newY }
      }
    }

    touchState.value.lastTouchDistance = distance
    touchState.value.lastTouchCenter = center
  }
}

const handleTouchEnd = (event: TouchEvent) => {
  event.preventDefault()
  event.stopPropagation()
  event.stopImmediatePropagation()

  if (event.touches.length === 0) {
    // 所有手指离开
    touchState.value.isTouching = false
    touchState.value.touches = []
    isDragging.value = false
    touchState.value.lastTouchDistance = 0
  } else if (event.touches.length === 1) {
    // 从双指变为单指
    const touch = event.touches[0]
    dragStart.value = {
      x: touch.clientX - canvasPosition.value.x,
      y: touch.clientY - canvasPosition.value.y
    }
    isDragging.value = true
  }
}

// 手势事件处理（Safari 专用）
const handleGestureStart = (event: Event) => {
  event.preventDefault()
  event.stopPropagation()
  event.stopImmediatePropagation()
  touchState.value.initialScale = canvasScale.value
  touchState.value.initialPosition = { ...canvasPosition.value }
}

const handleGestureChange = (event: Event) => {
  event.preventDefault()
  event.stopPropagation()
  event.stopImmediatePropagation()
  const gestureEvent = event as { scale?: number }

  if (gestureEvent.scale) {
    const newScale = Math.max(minScale, Math.min(maxScale, touchState.value.initialScale * gestureEvent.scale))
    canvasScale.value = newScale
  }
}

const handleGestureEnd = (event: Event) => {
  event.preventDefault()
  event.stopPropagation()
  event.stopImmediatePropagation()
  touchState.value.initialScale = canvasScale.value
  touchState.value.initialPosition = { ...canvasPosition.value }
}

// 全局事件处理函数（用于阻止浏览器默认手势）
const handleGlobalTouchStart = (event: TouchEvent) => {
  // 检查是否在画布容器内
  if (canvasContainer.value && canvasContainer.value.contains(event.target as Node)) {
    event.preventDefault()
    event.stopPropagation()
    event.stopImmediatePropagation()
  }
}

const handleGlobalTouchMove = (event: TouchEvent) => {
  // 检查是否在画布容器内
  if (canvasContainer.value && canvasContainer.value.contains(event.target as Node)) {
    event.preventDefault()
    event.stopPropagation()
    event.stopImmediatePropagation()
  }
}

const handleGlobalTouchEnd = (event: TouchEvent) => {
  // 检查是否在画布容器内
  if (canvasContainer.value && canvasContainer.value.contains(event.target as Node)) {
    event.preventDefault()
    event.stopPropagation()
    event.stopImmediatePropagation()
  }
}

const handleGlobalGestureStart = (event: Event) => {
  // 检查是否在画布容器内
  if (canvasContainer.value && canvasContainer.value.contains(event.target as Node)) {
    event.preventDefault()
    event.stopPropagation()
    event.stopImmediatePropagation()
  }
}

const handleGlobalGestureChange = (event: Event) => {
  // 检查是否在画布容器内
  if (canvasContainer.value && canvasContainer.value.contains(event.target as Node)) {
    event.preventDefault()
    event.stopPropagation()
    event.stopImmediatePropagation()
  }
}

const handleGlobalGestureEnd = (event: Event) => {
  // 检查是否在画布容器内
  if (canvasContainer.value && canvasContainer.value.contains(event.target as Node)) {
    event.preventDefault()
    event.stopPropagation()
    event.stopImmediatePropagation()
  }
}

// 辅助函数
const getTouchDistance = (touch1: Touch, touch2: Touch): number => {
  const dx = touch1.clientX - touch2.clientX
  const dy = touch1.clientY - touch2.clientY
  return Math.sqrt(dx * dx + dy * dy)
}

const getTouchCenter = (touch1: Touch, touch2: Touch): { x: number, y: number } => {
  return {
    x: (touch1.clientX + touch2.clientX) / 2,
    y: (touch1.clientY + touch2.clientY) / 2
  }
}

// 清理函数
const cleanup = () => {
  // 清理拖动状态
  if (isDragging.value) {
    isDragging.value = false
    document.removeEventListener('mousemove', handleGlobalMouseMove, { capture: true })
    document.removeEventListener('mouseup', handleGlobalMouseUp, { capture: true })

    // 恢复文本选择和光标
    document.body.style.userSelect = ''
    document.body.style.setProperty('-webkit-user-select', '')
    document.body.style.setProperty('-moz-user-select', '')
    document.body.style.setProperty('-ms-user-select', '')
    document.body.style.cursor = ''
  }

  // 清理触摸状态
  if (touchState.value.isTouching) {
    touchState.value.isTouching = false
    touchState.value.touches = []
    touchState.value.lastTouchDistance = 0
  }
}

// 生命周期钩子
onMounted(() => {
  document.addEventListener('keydown', handleKeyDown)

  // 添加全局触摸事件监听，阻止浏览器默认手势
  document.addEventListener('touchstart', handleGlobalTouchStart, { passive: false, capture: true })
  document.addEventListener('touchmove', handleGlobalTouchMove, { passive: false, capture: true })
  document.addEventListener('touchend', handleGlobalTouchEnd, { passive: false, capture: true })
  document.addEventListener('gesturestart', handleGlobalGestureStart, { passive: false, capture: true })
  document.addEventListener('gesturechange', handleGlobalGestureChange, { passive: false, capture: true })
  document.addEventListener('gestureend', handleGlobalGestureEnd, { passive: false, capture: true })

  // 监听页面卸载，确保清理状态
  window.addEventListener('beforeunload', cleanup)
  window.addEventListener('pagehide', cleanup)
})

onUnmounted(() => {
  document.removeEventListener('keydown', handleKeyDown)

  // 移除全局触摸事件监听
  document.removeEventListener('touchstart', handleGlobalTouchStart, { capture: true })
  document.removeEventListener('touchmove', handleGlobalTouchMove, { capture: true })
  document.removeEventListener('touchend', handleGlobalTouchEnd, { capture: true })
  document.removeEventListener('gesturestart', handleGlobalGestureStart, { capture: true })
  document.removeEventListener('gesturechange', handleGlobalGestureChange, { capture: true })
  document.removeEventListener('gestureend', handleGlobalGestureEnd, { capture: true })

  window.removeEventListener('beforeunload', cleanup)
  window.removeEventListener('pagehide', cleanup)

  // 清理所有状态
  cleanup()
})
</script>

<style scoped lang="scss">
.menu {
  padding: 5px 10px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  background-color: #EFEFF0;
  color: #55555D;
  font-size: 12px;
  line-height: 20px;

  .menu-left {
    display: flex;
    gap: 10px;
  }

  .menu-right {
    display: flex;
    align-items: center;
  }

  .zoom-controls {
    display: flex;
    align-items: center;
    gap: 6px;

    .zoom-input {
      width: 80px;

      :deep(.el-input__inner) {
        height: 24px;
        font-size: 12px;
        text-align: center;
      }

      :deep(.el-input-number__decrease),
      :deep(.el-input-number__increase) {
        width: 20px;
        height: 12px;
        line-height: 12px;
        font-size: 10px;
      }
    }

    .zoom-percent {
      font-size: 12px;
      color: #606266;
      margin-left: -2px;
    }

    .el-button {
      min-width: 32px;
      height: 24px;
      padding: 0 8px;
      font-size: 12px;
    }
  }

  .edit-icon {
    width: 10px;
    height: 10px;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .el-tag {
    cursor: pointer;
    border: none;
    background-color: transparent;
    color: #52525B;
  }

  :deep(.el-tag__close) {
    color: #52525B;
  }

  .tag-selected {
    color: #3B82F6;
    background-color: #fff;
  }
}



.form-designer-mid {
  height: 100%;
  box-sizing: border-box;
  border: 1px solid var(--layout-boder-color);
  border-radius: 8px;
  overflow: hidden;
}

.canvas-container {
  height: calc(100% - 50px);
  overflow: auto;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  position: relative;
  background-color: #E9E9E9;
  touch-action: none; // 禁用默认触摸行为，支持自定义手势
}

.form-canvas {
  width: 100%;
  height: 100%;
  background: white;
  transition: all 0.1s ease;
  position: absolute;
  left: 0;
  top: 0;
  user-select: none; // 防止拖动时选中文本
  touch-action: none; // 禁用默认触摸行为，支持自定义手势

  &.drag-over {
    border: 2px dashed #409eff;
    background: rgba(64, 158, 255, 0.05);
    box-shadow: 0 4px 20px rgba(64, 158, 255, 0.2);
  }

  &.dragging {
    transition: none; // 拖动时禁用过渡动画
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
    z-index: 10;
    outline: 2px solid rgba(64, 158, 255, 0.5);
    outline-offset: -2px;
  }
}

.drag-indicator {
  position: absolute;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(64, 158, 255, 0.9);
  color: white;
  padding: 8px 16px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 500;
  z-index: 1000;
  pointer-events: none;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  animation: dragPulse 1.5s ease-in-out infinite;
}

.drag-text {
  display: flex;
  align-items: center;
  gap: 8px;

  &::before {
    content: '↕';
    font-size: 14px;
    animation: dragMove 1s ease-in-out infinite;
  }
}

@keyframes dragPulse {

  0%,
  100% {
    opacity: 0.8;
    transform: translateX(-50%) scale(1);
  }

  50% {
    opacity: 1;
    transform: translateX(-50%) scale(1.05);
  }
}

@keyframes dragMove {

  0%,
  100% {
    transform: translateY(0);
  }

  50% {
    transform: translateY(-2px);
  }
}

.form-title {
  text-align: center;
  margin-bottom: 30px;
  padding-bottom: 20px;
  border-bottom: 1px solid #e4e7ed;

  h2 {
    margin: 0 0 10px 0;
    color: #303133;
    font-size: 24px;
    font-weight: 600;
  }

  p {
    margin: 0;
    color: #909399;
    font-size: 14px;
  }
}

.form-fields {
  height: 100%;
}

.field-item {
  position: relative;
  padding: 16px;
  border: 2px solid transparent;
  border-radius: 6px;
  background: #fafafa;
  transition: all 0.3s ease;
  cursor: pointer;

  &:hover {
    border-color: #c0c4cc;
    background: #f0f9ff;
  }

  &.selected {
    border-color: #409eff;
    background: #f0f9ff;
    box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
  }
}

.field-label {
  margin-bottom: 8px;
  font-weight: 500;
  color: #303133;

  .required {
    color: #f56c6c;
    margin-left: 2px;
  }
}

.field-input {

  .el-input,
  .el-select,
  .el-date-picker,
  .el-input-number {
    width: 100%;
  }

  .el-radio-group {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }
}

.field-actions {
  position: absolute;
  top: 8px;
  right: 8px;
  display: flex;
  gap: 4px;
  opacity: 0;
  transition: opacity 0.3s ease;

  .field-item.selected & {
    opacity: 1;
  }
}

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 400px;
  color: #909399;

  .empty-icon {
    width: 64px;
    height: 64px;
    margin-bottom: 16px;
    opacity: 0.5;
  }

  p {
    margin: 8px 0;
    font-size: 16px;
  }

  .empty-tip {
    font-size: 14px;
    color: #c0c4cc;
  }
}
</style>
